//写一个函数，求两个整数之和，要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
//
//
//
// 示例:
//
// 输入: a = 1, b = 1
//输出: 2
//
//
//
// 提示：
//
//
// a, b 均可能是负数或 0
// 结果不会溢出 32 位整数
//
//
// Related Topics 位运算 数学 👍 430 👎 0


//leetcode submit region begin(Prohibit modification and deletion)
function add(a: number, b: number): number {

    //? 将两个值无进制的运算结果（即a ^ b）赋值给a，将只保留进制的运算结果（即(a & b) << 1）赋值给b
    //? 循环计算到进制的运算结果为0时，a就是最终的结果了。
    while (b) {
        [a, b] = [a ^ b, (a & b) << 1]
    }
    return a;
};
//leetcode submit region end(Prohibit modification and deletion)
function add2(a=19, b=7) {
    /*
    ? 1. 先求一次不考虑进位的加法
       00->0 01->1 10->1, 11->0(进位，没处理)
    */
    let carry = a ^ b;
    /*
    ? 2. 计算进位
       两位均是1的过滤出来，11表示进位
       如果temp为0，表示没有进位，其实是可以直接相加的，不过是0的话再左移也没有影响
    */
    let temp = (a & b)<<1;
    /*
    ? 3.如果temp为0表示没有进位，比如：42+21，则直接相加返回
       101010 = 42
       010101 = 21
       000000 = 0，说明没有进位
    */
    if(temp === 0){
        //? 直接使用无进位加法求和的结果
        return carry;
    }
    let init;
    /*
      ? temp不为0表示有进位（可能不止一个1）
     ? （19+7）=> carry=20, temp = 6 相加（按同样的思路，直到没有进位了再求和 ）
      ? 19 + 7 => 20 + 6 => 18 + 8 => 26 + 0
    */
    while(temp){
        //? 变成了carry和temp的相加了(carry ^ temp);
        //? carry=20,temp=6求和
        init = carry ^ temp; //? 这里先不修改carry的值，下一步算进位还要用到
        //? 变成新的进位
        temp = (carry & temp)<<1; //? 20+6，18+8进位(temp)仍然不是0(按之前思路有进位，不能直接相加)
        //? 变成新值，用新数继续求和
        carry = init;
    }
    /*
        ? 最后求和（carray已经是temp为0时的求和结果）
        ? temp已经是0，因此carry就是最终结果
    */
    return carry; //? carray ^ temp
};
